import { pickedFaceData, Types } from '@amcax/base';
import {
  NumberInputFormat,
  PickInputRJSFFormat,
} from '@app-cad/common/components/command-form/constants';
import { PickableCommandForm } from '@app-cad/common/components/command-form/pickable';
import { useCommand } from '@app-cad/common/hooks/useCommand';
import { useTools } from '@app-cad/common/hooks/useTools';
import ReverseIconWidget from '@app-cad/common/RJSFWidgets/ReverseIconWidget';
import i18n from '@app-cad/common/utils/i18next';
import { isPlaneInfinite } from '@app-cad/common/utils/pickedData';
import { CurvedBaseCommand, CurvedCmdDialogParams } from '@app-cad/types';
import { RJSFSchema } from '@rjsf/utils';
import { useAsyncEffect } from 'ahooks';
import { useEffect, useRef, useState } from 'react';
import { useSwitchVisibility } from '../../feature/common/hooks/useSwitchVisibility';

import { MessageTip } from '@app-cad/common/utils/MessageTip';
import './index.scss';

type FormData = {
  plane1: pickedFaceData;
  plane2: pickedFaceData;
  count: number;
  reverseDir: boolean;
};

type Params = {
  plane1: string;
  plane2: string;
  count: number;
  reverseDir: boolean;
};

const CommandCopyPlane = ({ title, onClose, props }: CurvedCmdDialogParams) => {
  const baseRef = useRef([props?.params?.plane1, props?.params?.plane2]);
  useSwitchVisibility(baseRef.current, (props as any)?.dxid);

  const initData = {
    plane1: null,
    plane2: null,
    count: 2,
    reverseDir: false,
  };
  const [formData, setFormData] = useState<FormData>(initData);

  const { picker } = useTools();

  useAsyncEffect(async () => {
    if (props == null) {
      setFormData(initData);
      return;
    }

    const params = props.params as Params;

    await initEditDependency([params.plane1, params.plane2]);

    const plane1 = picker.generatePickObjByPickID(
      params.plane1,
    ) as pickedFaceData;
    const plane2 = picker.generatePickObjByPickID(
      params.plane2,
    ) as pickedFaceData;

    setFormData({
      plane1,
      plane2,
      count: params.count,
      reverseDir: params.reverseDir,
    });
  }, [props]);

  const isFormDataValid = () => {
    const { plane1, plane2, count } = formData;

    return (
      plane1 != null &&
      isPlaneInfinite(plane1) &&
      plane2 != null &&
      isPlaneInfinite(plane2) &&
      count !== null
    );
  };

  const preview = () => {
    if (!isFormDataValid()) {
      clear();
      return;
    }

    execute(true);
  };

  useEffect(() => {
    const { plane1, plane2 } = formData;

    if (
      (plane1 && !isPlaneInfinite(plane1)) ||
      (plane2 && !isPlaneInfinite(plane2))
    ) {
      MessageTip.error('输入元素必须是无限平面，请重新输入平面。');
    }

    preview();
  }, [formData]);

  const checkAndFinishDraw = async () => {
    if (!isFormDataValid()) {
      return;
    }

    await execute();

    onClose();
  };

  const {
    initEditDependency,
    initingEdit,
    clear,
    confirmCommand,
    isLoading,
    isPreviewLoading,
  } = useCommand('cmd-copy-plane', {
    commandName: 'CopyPlane',
    editDxid: (props as any)?.dxid,
    onClose,
    finishDraw: checkAndFinishDraw,
    previewDataModifier: (data) => {
      const profiles =
        data?.[0]?.faces?.map((face) => ({
          axis: face?.normals?.[0],
          location: face?.center,
          infinite: true,
        })) || [];

      return [{ ...data, type: Types.PLANE_COPY }, profiles];
    },
  });

  const execute = (preview = false) => {
    const { plane1, plane2, count, reverseDir } = formData;

    return confirmCommand(
      {
        a: {
          plane1: plane1.meshId,
          plane2: plane2.meshId,
          count,
          reverseDir,
        },
      },
      preview,
    );
  };

  const schema: RJSFSchema = {
    type: 'object',
    properties: {
      plane1: {
        type: 'string',
        format: PickInputRJSFFormat.PickPlane,
      },
      plane2: {
        type: 'string',
        format: PickInputRJSFFormat.PickPlane,
      },
      count: {
        type: 'number',
        title: '数量',
        default: 2,
        minimum: 1,
        maximum: 500,
        format: NumberInputFormat.Integer,
      },
      reverseDir: {
        type: 'boolean',
        title: '反向',
      },
    },
  };

  return (
    <PickableCommandForm
      disabled={initingEdit}
      onClose={onClose}
      title={title}
      submitLoading={isLoading || isPreviewLoading}
      widgets={{
        reverseIcon: ReverseIconWidget,
      }}
      schema={schema}
      formData={formData}
      onChange={(v) => {
        setFormData(v);
      }}
      extraUiSchema={{
        plane1: {
          'ui:placeholder': '请输入平面1',
          'ui:autofocus': true,
        },
        plane2: {
          'ui:placeholder': '请输入平面2',
        },
        reverseDir: {
          'ui:classNames': 'copy-plane-form-reverse-direction',
          'ui:widget': 'reverseIcon',
          'ui:label': false,
        },
      }}
      submitText='完成'
      onSubmit={checkAndFinishDraw}
      isFormDataValid={isFormDataValid()}
    />
  );
};

export const cmdCopyPlane: CurvedBaseCommand = {
  id: 'CmdCopyPlane',
  label: 'command.copy-plane',
  icon: 'commands/curved/copy-plane',
  create: (label, onClose, props) => (
    <CommandCopyPlane
      title={i18n.t(label)}
      onClose={onClose}
      props={props}
    />
  ),
};
